#ifndef XSNPP_H_061010
#define XSNPP_H_061010

#include <string>
#include <sstream>
#include <vector>
#include <memory>

#ifndef XSN_STATIC
#   ifdef _MSC_VER // Visual Studio specific macro
#	    ifdef XSN_DLL
#	    	define XSN_API __declspec(dllexport) 
#	    else
#			define XSN_API __declspec(dllimport) 
#	    endif
#   endif
#else
#   define XSN_API
#endif

namespace xsn
{
	class XSN_API Node;
	typedef std::shared_ptr<Node> NodePtr;
	typedef std::vector<NodePtr> NodePtrArray;
	typedef std::shared_ptr<const Node> ConstNodePtr;

	template<typename T> T xsnConvertTo(ConstNodePtr node);
	template<typename T> std::string xsnConvertFrom(const T& val);

	class XSN_API Node : public std::enable_shared_from_this<Node>
	{
	public:
		bool set(const std::string& src);
		bool set(const std::string& src,size_t& offset);
		std::string get() const;
		std::string get(size_t pos) const;
		ConstNodePtr getAttrib(size_t pos=1) const;
		ConstNodePtr getChild(size_t pos=0) const;
		NodePtr getParent() const;
		NodePtr getAttrib(size_t pos=1);
		NodePtr getChild(size_t pos=0);		
		NodePtr duplicate() const;
		NodePtr duplicateTree() const;
		size_t childCount() const;
		size_t attribCount() const;

		void attachChild(NodePtr node);
		void attachAttrib(NodePtr node);
		void detach();

		template<typename T> T get() const
		{
			return xsnConvertTo<T>(this->shared_from_this());
		}

		template<typename T> void set(const T& val)
		{
			this->attrib = xsnConvertFrom<T>(val);
		}

		template<> std::string get<std::string>() const
		{
			return this->attrib;
		}	

		template<> void set(const std::string& val)
		{
			this->attrib = val;
		}

		static NodePtr create();		
		static NodePtr create(const std::string& src);
		static NodePtr create(const std::string& src,size_t& offset);
		static NodePtr createFromFile(const std::string& filePath);	
	protected:
		std::string attrib;
		NodePtr parent;
		NodePtr next;
		NodePtr prev;
		std::vector<NodePtr> childs;

		Node();
		Node(const std::string& src);
		Node(const std::string& src,size_t& offset);
		bool setAttrib(const std::string& src, size_t& offset);
	};

	template<typename T> T xsnConvertTo(ConstNodePtr node)
	{
		T out;
		std::string strValue = node->get<std::string>();
		std::istringstream(strValue) >> out;
		return out;
	}

	template<typename T> std::string xsnConvertFrom(const T& val)
	{
		std::stringstream out;
		out << val;
		return out.str();
	}
}

#endif


